﻿using System.Data;
using System.IO;
using System;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;

namespace Home.Haushalt.Lib.Element
{
    /// <summary>
    /// 
    /// </summary>
    [ElementExtension("Element", 2)]
    public class Document : ElementBase
    {
        ///// <summary></summary>
        public bool PageChanged = false;

        #region CONSTANTS
        public new static readonly Type ElementType = typeof(Document);

        /// <summary></summary>
        public class Fields
        {
            public const string Id = ELEMENTPROPERTY_ID;
            public const string Label = ELEMENTPROPERTY_LABEL;
            public const string Description = ELEMENTPROPERTY_NOTE;
            public const string Date = "d";
            public const string OpponentId = "o";
            public const string PostenId = "z";
            public const string PostenExt1Id = "z1";
            public const string PostenExt2Id = "z2";
            public const string PostenExt3Id = "z3";
            public const string DocuTypeId = "a";
            public const string WayId = "w";
            public const string DirectionId = "r";
            public const string Crypted = "c";

            public const string UnboundPageCount = "pagecount";
            public const string UnboundImageOptionSummary = "image_optionsummary";
        }
        #endregion CONSTANTS

        /// <summary></summary>
        public override string PropertyFormCaption
        {
            get
            {
                ElementBase eb = ElementBase.Instantiate(typeof(Opponent));
                eb.Init(Row[Fields.OpponentId].ToInt());

                return (Row != null) ? string.Format("{0}: {1}", Row[Fields.Date].ToDateTime().ToString("dd.MM.yy"), eb.PropertyFormCaption) : "";
            }
        }

        /// <summary></summary>
        public bool InitialCrypted { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public Document() : base() { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parentDataRow"></param>
        public Document(DataRow parentDataRow) : base(parentDataRow) { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="encrypt">true = encrypt; false = decrypt</param>
        /// <returns></returns>
        public bool Crypt(bool encrypt)
        {
            bool result = true;

            foreach (DataRow row in DAO.GetSubRows(Page.ElementType, Page.Fields.DocumentId, ID))
            {
                Page pageObj = new Page(row);
                result = result & pageObj.Crypt(encrypt);
            }

            InitialCrypted = Row[Document.Fields.Crypted].ToBool(false);

            return result;
        }

        #region OVERRIDES

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override Dictionary<string, object> CalculateUnboundFields()
        {
            Dictionary<string, object> result = new Dictionary<string, object>();

            //Anzal der Dateien
            DataRow[] foundRows = DAO.GetSubRows(Page.ElementType, Page.Fields.DocumentId, ID);

            //Option summary image
            string wayKey = "way_" + this.Row[Fields.WayId].ToString();
            string directionKey = "direction_" + this.Row[Fields.DirectionId].ToString();
            Bitmap optionSummaryBitmap = Chips.CombineBitmaps(new Bitmap[] { DAO.ResourceImage[directionKey], DAO.ResourceImage[wayKey] });

            result.Add(Fields.UnboundPageCount, foundRows.Length);
            result.Add(Fields.UnboundImageOptionSummary, optionSummaryBitmap);

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parentDataRow"></param>
        internal override void Init(DataRow parentDataRow)
        {
            base.Init(parentDataRow);

            if (CheckColumnsInRow(Fields.Crypted))
            {
                InitialCrypted = Row[Fields.Crypted].ToBool(false);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override int Delete()
        {
            foreach (DataRow row in DAO.GetSubRows(Page.ElementType, Page.Fields.DocumentId, ID))
            {
                new Page(row).Delete();
            }

            return base.Delete();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override ElementBase New()
        {
            base.New();

            Row[Fields.Date] = DateTime.Now;

            if (ParentElement is Posten)
            {
                Row[Fields.PostenId] = ParentElement.Row[Posten.Fields.Id];
                Row[Fields.OpponentId] = ParentElement.Row[Posten.Fields.OpponentId];
            }
            else if (ParentElement is Opponent)
            {
                Row[Fields.OpponentId] = ParentElement.Row[Opponent.Fields.Id];
            }

            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override bool ValueChanged()
        {
            Application.DoEvents();

            bool result = base.ValueChanged();

            PageChanged = CheckPageChanged(
                Document.Fields.Date,
                Document.Fields.WayId,
                Document.Fields.DirectionId,
                Document.Fields.Id,
                Document.Fields.OpponentId,
                Document.Fields.DocuTypeId,
                Document.Fields.Crypted);

            result = PageChanged ? true : result;

            if (result)
            {
                result = result && (InputValidate().Count.Equals(0));
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="relevantFieldNames"></param>
        /// <returns>Ob Datei-Name geändert werden muss</returns>
        private bool CheckPageChanged(params string[] relevantFieldNames)
        {
            if (!PageChanged)
            {
                PageChanged = relevantFieldNames.Any(item => !Row[item].ToString().Equals(BindingRow[item].ToString()));
            }
            return PageChanged;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override List<string> InputValidate()
        {
            List<string> result = new List<string>();

            if (_selectedRows.Count.Equals(1))
            {
                if (BindingRow[Fields.Date].Equals(DBNull.Value)) result.Add(GetInputValidateMessage(this.GetType(), Fields.Date, "missing"));
                if (BindingRow[Fields.OpponentId].ToInt().Equals(0)) result.Add(GetInputValidateMessage(this.GetType(), Fields.OpponentId, "missing"));
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="raiseEvent"></param>
        public override void AcceptChanges(bool raiseEvent)
        {
            //Alten Stand merken
            DataTable oldTempTable = DAO.Tables[Document.ElementType].Clone();
            DataRow oldDocuRow = null;

            if (!Row.RowState.Equals(DataRowState.Detached))
            {
                oldTempTable.ImportRow(Row);
                oldDocuRow = oldTempTable.Rows[0];
            }

            //Änderungen akzeptieren
            base.AcceptChanges(false);

            RaiseAcceptChangesEvent(true, new HEventArgs("", oldDocuRow));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="raiseEvent"></param>
        public override void RejectChanges(bool raiseEvent)
        {
            base.RejectChanges(false);

            foreach (DataRow pageRow in DAO.GetRows(Page.ElementType, "{0} = {1} and {2} = -1", Page.Fields.DocumentId, ID, Page.Fields.Id))
            {
                pageRow.Delete();
                Application.DoEvents();
            }

            RaiseRejectChangesEvent(true);
        }


        #endregion OVERRIDES

    }
}
